#ifndef DBSTORAGE_PACKAGE_DB_STORAGE_HPP
#define DBSTORAGE_PACKAGE_DB_STORAGE_HPP

#include "DbStorage/DbStorageBase.hpp"
#include "Storage/PackageStorage.hpp"
#include <boost/tuple/tuple.hpp>
#include <map>

namespace CaseDB { class RecordSet; }
namespace Model { class Package; class Project;}

namespace DbStorage
{

/// @ingroup DbStorage
/// @brief It specializes the generic package storage for database operations.
class DBSTORAGE_API PackageDbStorage: public Storage::PackageStorage, public DbStorageBase
{
public:
	/// @brief It initializes the storage.
	/// @param factory the storage factory to be used for accessing other dependent storages when needed.
	/// @param pConnection the database connection to be used for storages.
	PackageDbStorage( Storage::StorageFactory& factory, CaseDB::Connection* pConnection);

	/// @brief It loads the packages corresponding to the specified project and adds them to the project.
	/// @param prjToLoad the project needing package loading.
	virtual void loadPackages( Model::Project& prjToLoad);

	/// @sa Storage::PackageStorage::deepSearchByStoredID( Model::Package* , const boost::any& ) const
	virtual Model::Package* deepSearchByStoredID( Model::Package* pCurPackage, const boost::any& storedID) const;

private:
	/// @brief Structure for getting raw package data from database, before reconstructing the package hierarchy.
	typedef boost::tuples::tuple< int, std::string, std::string> PackageDescription;

	/// @brief Structure for quick looking up of raw package data, indexed by parent package id.
	typedef std::multimap< int, PackageDescription> PackageLookup;

	/// @brief It converts the record set loaded from database to PackageLookup structure for quicker package hierarchy 
	///	reconstruction.
	void bulkLoad( const CaseDB::RecordSet& results, PackageLookup& loadedBulk);

	/// @brief It creates the package hierachy in the specified project, using the raw data from the lookup collection.
	void processBulk( Model::Project& prjToLoad, PackageLookup& loadedLookup);

	/// @brief It creates the children of the specified parent using the raw data from the provided lookup collection.
	void processChildrenOf( Model::Package& parent, PackageLookup& loadedBulk);
};

} // namespace DbStorage

#endif // DBSTORAGE_PACKAGE_DB_STORAGE_HPP
